package cn.itcast.nems.common.util;

import cn.itcast.ic.common.exception.v2.BizExceptionProducer;
import cn.itcast.nems.studentrecord.enumeration.StudentRecordErrorBodyEnum;
import com.alibaba.fastjson2.util.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.util.Calendar;
import java.util.Date;

public class IDCardUtil {
	static Logger logger = LoggerFactory.getLogger(IDCardUtil.class);

	/**
	 * 根据身份证号解析性别
	 * 
	 * @param idcard
	 * @return 0：女,1：男，-1：未知
	 */
	public static int parseSex(String idcard) {
		int sex = -1;
		if (isValidate(idcard)) {
			char c = idcard.charAt(idcard.length() - 1);
			if (c >= 48 && c <= 57) {
				int i = c - 48;
				if (i % 2 == 0) {
					sex = 0;
				} else {
					sex = 1;
				}
			} else if (c == 'X' || c == 'E' || c == 'x' || c == 'e') {
				sex = 1;
			} else {
				sex = 0;
			}
		}
		return sex;
	}

	/**
	 * 根据身份证号倒数第二位判断解析性别
	 * 
	 * @param idcard
	 * @return 0：女,1：男，-1：未知
	 */
	public static int parseSex2(String idcard) {
		int sex = -1;
		if (isValidate(idcard)) {
			char c = idcard.charAt(idcard.length() - 2);
			int i = Integer.parseInt(String.valueOf(c));
			sex = i % 2;
		}
		return sex;
	}

	/**
	 * 根据身份证号解析年龄
	 * 
	 * @param idcard
	 * @return -1身份证号不合法
	 */
	public static int parseAge(String idcard) {
		return parseExactAge(idcard);
	}

	/** 精确到年月日的年龄 */
	public static int parseExactAge(String idcard) {
		Date birthday = parseBirthday(idcard);
		return calAge(birthday, new Date());
	}

	/**
	 * 计算年龄
	 * @param idcard 身份证号
	 * @param date 指定日期
	 * @return 年龄
	 */
	public static int parseAge (String idcard, Date date) {
		Date birthday = parseBirthday(idcard);
		return calAge(birthday, date);
	}

	/** 计算到指定日期时的年龄 */
	public static int calAge(Date birthday, Date date) {
		int age = -1;
		if (birthday != null) {
			Calendar cal = Calendar.getInstance();
			if (cal.before(birthday)) {
				throw new IllegalArgumentException("生日在当前日期之后，不能计算");
			}
			cal.setTime(date);
			int yearNow = cal.get(Calendar.YEAR);
			int monthNow = cal.get(Calendar.MONTH);
			int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
			
			cal.setTime(birthday);
			int yearBirth = cal.get(Calendar.YEAR);
			int monthBirth = cal.get(Calendar.MONTH);
			int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);

			age = yearNow - yearBirth;

			if (monthNow <= monthBirth) {
				if (monthNow == monthBirth) {
					if (dayOfMonthNow < dayOfMonthBirth)
						age--;
				} else {
					age--;
				}
			}
		}
		return age;
	}
	/**
	 * <p>
	 * 根据身份证和生日获取年龄 ， 优先从身份证提取
	 * </p>
	 *
	 * @param idcrad 身份证号码
	 * @param birthday 生日
	 * @author zhouwei
	 * @since 2024/3/15 10:12 AM
	 **/
	public static int getAge(String idcrad , Date birthday) {
		int age = 0;
		try {
			if (StringUtils.hasText(idcrad) && idcrad.length() > 5) {
				age = IDCardUtil.parseAge(idcrad);
			}
			if (age <= 0) {
				age = IDCardUtil.calAge(birthday, new Date());
			}
		} catch (Exception e) {
			logger.warn("【年龄解析失败】idcrad：{} , 学生信息：{}", idcrad , DateUtils.format(birthday));
			BizExceptionProducer.throwProduce(e, StudentRecordErrorBodyEnum.STUDENT_AGE_FORMAT_ERROR);
		}
		return age;
	}

	/**
	 * <p>
	 * 根据年龄获取年龄等级
	 * </p>
	 *
	 * @param age 年龄
	 * @author zhouwei
	 * @since 2024/3/15 10:12 AM
	 **/
	public static int ageRank(int age) {
		if (age < 18) {
			return 0;
		}
		if (age <= 21) {
			return 1;
		}
		if (age <= 25) {
			return 2;
		}
		if (age <= 29) {
			return 3;
		}
		return 4;
	}

	/** 是否成年 */
	public static boolean isAdult(String idcard) {
		int age = parseExactAge(idcard);
		return age >= 18;
	}

	/**
	 * 根据身份证判断到指定时间是否成年
	 * 
	 * @param idcard
	 * @param date
	 * @return
	 */
	public static boolean isAdult(String idcard, Date date) {
		if (StringUtils.hasText(idcard)) {
			Date birthday = parseBirthday(idcard);
			int age = calAge(birthday, date);
			return age >= 18;
		}
		return false;
	}

	/**
	 * 通过身份证号解析出生日
	 * 
	 * @param idcard 身份证号
	 * @return 生日 ，身份证为空或异常返回 null
	 */
	public static Date parseBirthday(String idcard) {
		Date birthday = null;
		if (isValidate(idcard)) {
			try {
				idcard = idcard.trim();
				if (idcard.length() == 18) {
					String date = idcard.substring(6, 14);
					birthday = DateUtils.parseDate(date, "yyyyMMdd");
				} else {
					String date = idcard.substring(6, 12);
					birthday = DateUtils.parseDate(date, "yyMMdd");
				}
			} catch (Exception e) {
				logger.warn(e.getMessage());
			}
		}
		return birthday;
	}

	public static boolean isValidate(String idcard) {
		boolean b = false;
		if (StringUtils.hasText(idcard) && (idcard.trim().length() == 18 || idcard.trim().length() == 15)) {
			b = true;
		}
		return b;
	}
}
